from enum import Enum
import uuid
from dotenv import load_dotenv
from fastapi import Request
from pydantic import BaseModel
from datetime import datetime, timedelta
from typing import Dict
from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
import logging
    
load_dotenv()
# 支付宝配置
alipay_client_config = AlipayClientConfig()
alipay_client_config.server_url = "https://openapi.alipay.com/gateway.do"
alipay_client_config.app_id = "2021005158637850"
with open('alipay_privkey.pem', 'r') as f:
    alipay_client_config.app_private_key = f.read()
with open('alipay_pubkey.pem', 'r') as f:
    alipay_client_config.alipay_public_key = f.read()
alipay_client_config.sign_type='RSA2'

logger = logging.getLogger(__name__)
alipay_client = DefaultAlipayClient(alipay_client_config, logger)
    
class PayController:
    class Status(Enum):
        WAITING = "waiting"
        SUCCESS = "success"
        EXPIRED = "expired"
        FAILED = "failed"
    
    class Transaction:
        def __init__(self, price: int):
            self.out_trade_no = f"order_{datetime.now().strftime('%Y%m%d%H%M%S')}_{str(uuid.uuid4())[:8]}"
            self.total_amount = str(price)
            self.status = PayController.Status.WAITING
            self.created_at = datetime.now()
    
    def __init__(self):
        self.alipay_client = alipay_client
        self.transactions: Dict[str, PayController.Transaction] = {}
    
    def create_transaction(self, price: int):
        transaction = PayController.Transaction(price)
        self.transactions[transaction.out_trade_no] = transaction
        return transaction
    
    def success(self, out_trade_no: str):
        transaction = self.transactions.get(out_trade_no)
        if transaction:
            transaction.status = PayController.Status.SUCCESS
            return transaction
        return None
    
    def expired(self, out_trade_no: str):
        transaction = self.transactions.get(out_trade_no)
        if transaction:
            transaction.status = PayController.Status.EXPIRED
            return transaction
        return None
    
    def failed(self, out_trade_no: str):
        transaction = self.transactions.get(out_trade_no)
        if transaction:
            transaction.status = PayController.Status.FAILED
            return transaction
        return None
    
    def _gc(self):
        for out_trade_no, transaction in self.transactions.items():
            if transaction.status != PayController.Status.WAITING and transaction.created_at < datetime.now() - timedelta(minutes=10):
                self.transactions.pop(out_trade_no)
    
pay_controller = PayController()
    

def is_mobile_device(request: Request) -> bool:
    user_agent = request.headers.get("user-agent", "").lower()
    
    # 移动设备的特征关键词
    mobile_keywords = [
        "android",
        "iphone",
        "ipod",
        "ipad",
        "windows phone",
        "webos",
        "blackberry",
        "mobile",
        "phone",
        "midp",
        "opera mobi",   
        "opera mini",
        "ucweb",
        "alipay",
        "alipayclient",
        "micromessenger",  # 微信浏览器
        "miniprogram"      # 小程序环境
    ]
    
    # 如果包含移动设备关键词，则判定为移动设备
    return any(keyword in user_agent for keyword in mobile_keywords)    


# /alipay/success?charset=utf-8
# &out_trade_no=order_20250613190043_5f52932d
# &method=alipay.trade.page.pay.return
# &total_amount=1.00
# &sign=W7OO6nPXovySPP3YHDThO%2FqTiDNi2Hk2U7dUOvQhgqYFx5KMVjCQaHS03qvcrfhpSOqfPEo6u0ZsprjB70pGLyuA1ajfoNgSslFECiTyztbTidsCRKszr9LTUT5lht25qUcFop9qwOha00OhorHgsmCkOZhwWGQI8FszsH%2BEBBUu2AXRY0AINfXOrcRofa6glN%2F6vKPhCGu27rRz4PexiwhrQwMq811v6N7LqUoPXMidcPmPI6kPwqfQbKe31mV360aII2oIcvW7o9TABHXmpA8QSgFHK1i3V4EIYDVoFrNwKh%2FngK0bvqPJD6GxwYnQ7%2FG9SDfhSy7p950b3LgkQA%3D%3D
# &trade_no=2025061322001430231436519891
# &auth_app_id=2021005158637850
# &version=1.0
# &app_id=2021005158637850
# &sign_type=RSA2
# &seller_id=2088051979448696
# &timestamp=2025-06-13+19%3A01%3A08
class SuccessResponse(BaseModel):
    charset: str
    out_trade_no: str
    method: str
    sign: str
    total_amount: str
    trade_no: str
    auth_app_id: str
    version: str
    app_id: str
    sign_type: str
    seller_id: str
    timestamp: str

# gmt_create=2025-06-13+19%3A01%3A31
# &charset=utf-8
# &gmt_payment=2025-06-13+19%3A01%3A35
# &notify_time=2025-06-13+19%3A01%3A36
# &subject=%E5%95%86%E5%93%81%E8%B4%AD%E4%B9%B0
# &sign=iQe6abffh7sRrThkkGNigP87Y%2FX1yGtaJdZ5zy6S6KQkDk8CLgTL371Ji6UapzDzMugZllwGQFBuGyFelzD3SLnpsdgTlz%2Ba%2BKmzmYTGhVky6r1MAYzaAi5rLKVp8RbieZ2F9mLv%2BBrHtmMLx88wawufw9HOpDTmZv5rMqwCgagL%2FWIYpN6z7hDju96W3Cd%2BJZczCQz39uL8IDetHeNffE%2B27AlGOZWTE7oUVaWX5gUqo%2BuLX1qWkUghSJvDRM2NB7rIWambnDqggLOga7yLQL0Soi18%2BNJnj6EiDmkCZJhPsdr00WKHMhUO36hs0vIyffxX8ncJYYLNN7XiV70Lwg%3D%3D
# &merchant_app_id=2021005158637850
# &buyer_open_id=023ISg7B33KVUOhl44thawRF2yiTVIwf0aTbT4itSpNwn02
# &invoice_amount=1.00
# &version=1.0
# &notify_id=2025061301222190135030231472213865
# &fund_bill_list=%5B%7B%22amount%22%3A%221.00%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D
# &notify_type=trade_status_sync
# &out_trade_no=order_20250613190129_871677b1
# &total_amount=1.00
# &trade_status=TRADE_SUCCESS
# &trade_no=2025061322001430231436413429
# &auth_app_id=2021005158637850
# &receipt_amount=1.00
# &point_amount=0.00
# &buyer_pay_amount=1.00
# &app_id=2021005158637850
# &sign_type=RSA2
# &seller_id=2088051979448696
class NotifyResponse(BaseModel):
    gmt_create: str
    charset: str
    gmt_payment: str
    notify_time: str
    subject: str
    sign: str
    merchant_app_id: str
    buyer_open_id: str
    invoice_amount: str
    version: str
    notify_id: str
    fund_bill_list: str
    notify_type: str
    out_trade_no: str
    total_amount: str
    trade_status: str
    trade_no: str
    auth_app_id: str
    receipt_amount: str
    point_amount: str
    buyer_pay_amount: str
    app_id: str
    sign_type: str
    seller_id: str
